/**
 * 
 */
package org.pl.lfmgfw;

import java.io.IOException;
import java.io.InputStream;
import java.util.prefs.Preferences;

import javax.swing.JOptionPane;

import net.sf.libgrowl.Application;
import net.sf.libgrowl.GrowlConnector;
import net.sf.libgrowl.Notification;
import net.sf.libgrowl.NotificationType;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ShellAdapter;
import org.eclipse.swt.events.ShellEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.program.Program;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Tray;
import org.eclipse.swt.widgets.TrayItem;

import de.umass.lastfm.ImageSize;
import de.umass.lastfm.Track;
import de.umass.lastfm.User;

public class Main {
	
	private static final String API_KEY = "920db4dc609384608635dfbbf4c89393";
	private static final NotificationType NEW_SONG = new NotificationType("NEWSONG", "New song");
	private static final int TIME = 1000;
	private static final String APP_NAME = "Last.fm - Growl";
	
	private static boolean trackEquals(Track t1, Track t2) {
		return t1 == t2 || (t1 != null && t2 != null && t1.getName().equals(t2.getName()) && t1.getArtist().equals(t2.getArtist()) && t1.getAlbum().equals(t2.getAlbum()));
	}

	public static void main(String[] args) {
		try {
			new Main();
		} catch (Exception e) {
			e.printStackTrace();
			JOptionPane.showMessageDialog(null, e.getLocalizedMessage());
		}
	}
	
	private Track currentTrack;
	private Application application;
	private GrowlConnector conn;
	private Notification notification;
	private Preferences preferences;
	private Display display;
	private Shell shell;
	private Image appIcon;
	private TrayItem trayItem;
	private MenuItem firstMenuItem;
	
	public Image getAppIcon() {
		if (appIcon == null) {
			InputStream is = ClassLoader.getSystemResourceAsStream("LastFM_64.png");
			if (is == null) {
				appIcon = new Image(display, 16, 16);
			} else {
				try {
					appIcon = new Image(display, is);
				} finally {
					try {
						is.close();
					} catch (IOException e) {
					}
				}
			}
		}
		return appIcon;
	}
	
	public Main() throws Exception {
		conn = new GrowlConnector();
		preferences = Preferences.userNodeForPackage(Main.class);
		
		display = new Display();
		createShell();
		display.asyncExec(createInitRunnable());
		while (!shell.isDisposed ()) {
			if (!display.readAndDispatch ()) display.sleep ();
		}
		appIcon.dispose();
		display.dispose();
	}
	
	private Runnable createInitRunnable() {
		return new Runnable() {
			public void run() {
				//init growl
				application = new Application(APP_NAME);
				conn.register(application, new NotificationType[]{NEW_SONG});
				notification = new Notification(application, NEW_SONG, "Currently playing", null);
				
				//init new song timer
				Runnable timer = new Runnable() {
					public void run() {
						for (Track track : User.getRecentTracks(getUsername(), 1, API_KEY, 1).getPageResults()) {
							if (track.isNowPlaying()) {
								if (!trackEquals(track, currentTrack)) {
									currentTrack = track;
									notification.setText(track.getArtist() + " - " + track.getName() + "\n" + track.getAlbum());
									notification.setIcon(track.getImageURL(ImageSize.MEDIUM));
									conn.notify(notification);
									if (trayItem != null) {
										trayItem.setText(track.getArtist() + " - " + track.getName());
										firstMenuItem.setEnabled(track.getLastFmInfo(Track.TRACK_PAGE) != null);
										firstMenuItem.setText(trayItem.getText());
									}
								}
								break;
							}
						}
						display.timerExec(TIME, this);
					}
				};
				display.timerExec(TIME, timer);
			}
		};
	}

	private void createShell() {
		shell = new Shell(display, SWT.DIALOG_TRIM);
		shell.addShellListener(new ShellAdapter() {
			public void shellClosed(ShellEvent e) {
				e.doit = false;
				shell.setVisible(false);
			}
		});
		shell.setText(APP_NAME);
		shell.setBounds(0,0,0,0);
		
		createTrayItem();
		
		shell.open();
		shell.setVisible(false);
		shell.setBounds(0,0,250, 150);
		//build shell components
		
	}

	private void createTrayItem() {
		final Tray tray = display.getSystemTray ();
		if (tray == null) {
			System.out.println("The system tray is not available");
		} else {
			final Menu menu = new Menu (shell, SWT.POP_UP);
			firstMenuItem = new MenuItem (menu, SWT.PUSH);
			firstMenuItem.addListener(SWT.Selection, new Listener () {
				public void handleEvent (Event event) {
					if (currentTrack != null) {
						String trackPage = currentTrack.getLastFmInfo(Track.TRACK_PAGE);
						if (trackPage != null) {
							Program.launch(trackPage);
						}
					}
				}
			});
			new MenuItem(menu, SWT.SEPARATOR);
			MenuItem mi = new MenuItem (menu, SWT.PUSH);
			mi.setText("Show preferences");
			mi.addListener (SWT.Selection, new Listener () {
				public void handleEvent (Event event) {
					shell.open();
				}
			});
			menu.setDefaultItem(mi);
			mi = new MenuItem (menu, SWT.PUSH);
			mi.setText("Quit");
			mi.addListener (SWT.Selection, new Listener () {
				public void handleEvent (Event event) {
					shell.dispose();
				}
			});
			trayItem = new TrayItem (tray, SWT.NONE);
			trayItem.setToolTipText(APP_NAME);
			trayItem.addListener (SWT.DefaultSelection, new Listener () {
				public void handleEvent (Event event) {
					menu.getDefaultItem().notifyListeners(SWT.Selection, new Event());
				}
			});
			trayItem.addListener (SWT.MenuDetect, new Listener () {
				public void handleEvent (Event event) {
					menu.setVisible (true);
				}
			});
			trayItem.setImage(getAppIcon());
		}
	}
	
	private String getUsername() {
		return preferences.get("username", null);
	}
}
